﻿using System;
using System.Collections.Generic;
using System.Text;

namespace ASCII_operations
{
    public class ASCII
    {
         
        int[,] Values; 
        string FileName;
        int ncols;
        int nrows;
        float xllcorner;
        float yllcorner;
        int cellsize;
        int NODATA_value;

        public int this[int r, int c]
        {
            get { return Values[r,c]; }
            set { Values[r, c] = value; }
        }

        
        public int Ncols
        {
            get
            {
                return ncols;
            }
        }
        public int Nrows
        {
            get
            {
                return nrows;
            }
        }

        public delegate int Random(double mean, double standard_deviation);
        public delegate int CappedRandom(double mean, double standard_deviation,int min, int max);

        public void ReplaceValues(int from, CappedRandom R, double mu, double sigma, int min, int max)
        {
            for (int r = 0; r < nrows; r++)
            {
                for (int c = 0; c < ncols; c++)
                {
                    if (Values[r, c] == from) Values[r, c] = R(mu, sigma, min, max); ;
                }
            }

        }

        public void ReplaceValues(int from, Random R, double mu, double sigma)
        {
            for (int r = 0; r < nrows; r++)
            {
                for (int c = 0; c < ncols; c++)
                {
                    if (Values[r, c] == from) Values[r, c] = R(mu, sigma); ;
                }
            }

        }
        
        public void ReplaceValues(int from, int to)
        {
            for (int r = 0; r < nrows; r++)
            {
                for (int c = 0; c < ncols; c++)
                {
                    if (Values[r, c] == from) Values[r, c] = to;
                }
            }
            if (ContainsValue(from) && from != to)
            {
                throw new System.Exception("Cannot contain value "+ from);
            }
        }
         
        public bool ContainsValue(int v)
        {
            for (int r = 0; r < nrows; r++)
            {
                for (int c = 0; c < ncols; c++)
                {
                    if (Values[r, c] == v) return true;
                }
            }
            return false;
        }
        public void Write(string filename)
        {
            

            this.FileName = filename;
            List<string> Content = new List<string>();
            Content.Add("ncols         " + ncols);
            Content.Add("nrows         " + nrows);
            Content.Add("xllcorner     " + xllcorner);
            Content.Add("yllcorner     " + yllcorner);
            Content.Add("cellsize      " + cellsize);
            Content.Add("NODATA_value  " + NODATA_value);

            for (int r = 0; r < nrows; r++)
            {
                string line ="";
                for (int c = 0; c < ncols; c++)
                {
                    line += Values[r, c] + " ";
                }
                Content.Add(line);
            }
           

            System.IO.File.WriteAllLines(filename, Content.ToArray());
          
        }
        private void Read()
        {
            string[] content = System.IO.File.ReadAllLines(FileName);

            for (int hdrcount = 0; hdrcount < content.Length; hdrcount++)
            {
                string[] terms = content[hdrcount].Trim().Split(' ');
                if (terms[0] == "ncols") ncols = int.Parse(terms[terms.Length-1]);
                if (terms[0] == "nrows") nrows = int.Parse(terms[terms.Length - 1]);
                if (terms[0] == "xllcorner") xllcorner = float.Parse(terms[terms.Length-1]);
                if (terms[0] == "yllcorner") yllcorner = float.Parse(terms[terms.Length - 1]);
                if (terms[0] == "cellsize") cellsize = int.Parse(terms[terms.Length - 1]);
                if (terms[0] == "NODATA_value") NODATA_value = int.Parse(terms[terms.Length - 1]);
            }
            Values = new int[nrows, ncols];
            for (int r = 0; r < nrows; r++)
            {
                string[] val = content[6 + r].Trim().Split(' ');

                for (int c = 0; c < ncols; c++)
                {
                    Values[r, c] = int.Parse(val[c].Trim());
                }
            }

        }
        public ASCII(ASCII ascii)
        {
            this.cellsize = ascii.cellsize;
            this.nrows = ascii.nrows;
            this.ncols = ascii.ncols;
            this.xllcorner = ascii.xllcorner;
            this.yllcorner = ascii.yllcorner;
            this.cellsize = ascii.cellsize;
            this.NODATA_value = ascii.NODATA_value;

            Values = new int[nrows, ncols];
            for (int r = 0; r < nrows; r++)
            {
                for (int c = 0; c < ncols; c++)
                {
                    Values[r, c] = NODATA_value;
                }
            }
        }
       
        public ASCII(string filename)
        {
            FileName = filename;
            Read();
        }
    }
}
